import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:powerful_table/powerful_table.dart';

typedef Widget _FreeTableItemBuilder(
  BuildContext context,
  TableIndexPath indexPath,
);

typedef double _FreeCellHeightBuilder(
  BuildContext context,
  int row,
);

typedef void _FreeCellTapCallBack(
  BuildContext context,
  int row,
);

typedef double _CellItemWidthBuilder(
  BuildContext context,
  int index,
);

typedef Widget _CellItemBuilder(
  BuildContext ctx,
  int index,
);

class TableIndexPath extends Object {
  const TableIndexPath(this.row, this.index);
  final int row;
  final int index;
}

class FreeTableCellStyle extends Object {
  FreeTableCellStyle({
    _FreeCellHeightBuilder? heightBuilder,
    _CellItemWidthBuilder? itemWidthBuilder,
    this.splitLinePadding: const EdgeInsets.symmetric(vertical: 0),
    this.splitLineColor: Colors.black26,
    this.prefix: const SizedBox(width: 10),
    this.suffix: const SizedBox(width: 10),
    this.showShadow: true,
    this.shadowOffset: 10.0,
  }) {
    this.heightBuilder = heightBuilder ?? _defaultCellHeightBuilder;
    this.itemWidthBuilder = itemWidthBuilder ?? _defaultItemWidthBuilder;
  }

  double _defaultCellHeightBuilder(BuildContext ctx, int row) {
    return 44;
  }

  double _defaultItemWidthBuilder(BuildContext ctx, int index) {
    return 100;
  }

  /// 高度构造器
  late final _FreeCellHeightBuilder heightBuilder;

  /// item宽度构造器
  late final _CellItemWidthBuilder itemWidthBuilder;

  /// 分割线外边距
  final EdgeInsets splitLinePadding;

  /// 分割线颜色
  final Color splitLineColor;

  /// cell头部
  final Widget prefix;

  /// cell尾部
  final Widget suffix;

  /// 是否展示阴影
  final bool showShadow;

  /// 阴影偏移量
  final double shadowOffset;
}

/// 支持上下左右四个方向滚动的组件，第一列固定，其他的可左右滚动
// ignore: must_be_immutable
class SliverFreeTable extends StatefulWidget {
  SliverFreeTable({
    Key? key,
    UnifyScrollController? horizontalController,
    required this.itemBuilder,
    FreeTableCellStyle? cellStyle,
    this.onTapCell,
    this.rowCount: 0,
    this.itemCount: 0,
  }) : super(key: key) {
    this.horizontalController = horizontalController ?? UnifyScrollController();
    this.cellStyle = cellStyle ?? FreeTableCellStyle();
  }

  /// 横向滚动控制器
  late final UnifyScrollController horizontalController;

  /// 单元格构造器
  final _FreeTableItemBuilder itemBuilder;

  /// cell风格
  late final FreeTableCellStyle cellStyle;

  /// cell点击事件
  final _FreeCellTapCallBack? onTapCell;

  /// 行数
  final int rowCount;

  /// 每行列数
  final int itemCount;

  @override
  _SliverFreeTableState createState() => _SliverFreeTableState();
}

class _SliverFreeTableState extends State<SliverFreeTable> {
  /// 列宽
  late List<double> _itemWidths;
  bool _showShadow = false;

  @override
  void initState() {
    super.initState();
    widget.horizontalController.addListener(_horizontalControllerListener);
  }

  @override
  void dispose() {
    widget.horizontalController.removeListener(_horizontalControllerListener);
    super.dispose();
  }

  @override
  void didUpdateWidget(SliverFreeTable oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget != widget) {
      widget.horizontalController.addListener(_horizontalControllerListener);
    }
  }

  void _horizontalControllerListener() {
    if (widget.cellStyle.showShadow == false) return;
    bool offsetIsZero = widget.horizontalController.offset == 0;
    if (offsetIsZero == _showShadow) {
      _showShadow = !offsetIsZero;
      setState(() {});
    }
  }

  Widget _cellBuilder(ctx, row) {
    return _FreeTableCell(
      horizontalController: widget.horizontalController,
      height: widget.cellStyle.heightBuilder(ctx, row),
      splitLineColor: widget.cellStyle.splitLineColor,
      splitLinePadding: widget.cellStyle.splitLinePadding,
      prefix: widget.cellStyle.prefix,
      suffix: widget.cellStyle.suffix,
      itemCount: widget.itemCount,
      showShadow: _showShadow,
      shadowOffset: widget.cellStyle.shadowOffset,
      itemBuilder: (ctx, index) {
        return widget.itemBuilder(ctx, TableIndexPath(row, index));
      },
      itemWidthBuilder: (ctx, index) {
        return _itemWidths[index];
      },
      onTap: () {
        if (widget.onTapCell != null) {
          widget.onTapCell!(ctx, row);
        }
      },
    );
  }

  void _reloadItemWidths(BuildContext ctx) {
    this._itemWidths = [];
    for (var i = 0; i < widget.itemCount; i++) {
      this._itemWidths.add(widget.cellStyle.itemWidthBuilder(ctx, i));
    }
  }

  @override
  Widget build(BuildContext context) {
    _reloadItemWidths(context);
    return SliverList(
      delegate: SliverChildBuilderDelegate(
        _cellBuilder,
        childCount: widget.rowCount,
      ),
    );
  }
}

/// 表格的cell，cell中左边固定一个Widget，右边的Widget可以左右滚动
class _FreeTableCell extends StatelessWidget {
  const _FreeTableCell({
    Key? key,
    required this.horizontalController,
    required this.itemBuilder,
    required this.itemWidthBuilder,
    this.itemCount: 0,
    this.height: 40,
    this.splitLinePadding: const EdgeInsets.all(0),
    this.splitLineColor: Colors.transparent,
    this.onTap,
    this.color: Colors.white,
    this.prefix: const SizedBox(),
    this.suffix: const SizedBox(),
    this.showShadow: false,
    this.shadowOffset: 0.0,
  }) : super(key: key);

  /// 左右滚动的控制器
  final UnifyScrollController horizontalController;

  /// 高度
  final double height;

  /// 分割线外边距
  final EdgeInsets splitLinePadding;

  /// 分割线颜色
  final Color splitLineColor;

  /// 点击事件
  final VoidCallback? onTap;

  /// 背景颜色
  final Color color;

  /// item构造器
  final _CellItemBuilder itemBuilder;

  /// item宽度构造器
  final _CellItemWidthBuilder itemWidthBuilder;

  /// 数量
  final int itemCount;

  final Widget prefix;
  final Widget suffix;
  final bool showShadow;
  final double shadowOffset;

  Widget _itemBuilder(BuildContext ctx, int index) {
    return SizedBox(
      width: itemWidthBuilder(ctx, index + 1),
      child: Center(
        child: itemBuilder(ctx, index + 1),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    Widget left = SizedBox(
      width: itemWidthBuilder(context, 0),
      child: itemBuilder(context, 0),
    );

    Widget right = ListView.builder(
      scrollDirection: Axis.horizontal,
      itemBuilder: _itemBuilder,
      itemCount: itemCount - 1,
      controller: horizontalController,
    );
    Widget content = Row(
      children: [
        prefix,
        left,
        Expanded(child: right),
        suffix,
      ],
    );
    Widget line = Container(
      margin: splitLinePadding,
      height: 0.5,
      color: splitLineColor,
    );

    Widget shadow = Offstage(
      offstage: !showShadow,
      child: Container(
        width: 10,
        height: 100,
        decoration: BoxDecoration(
          gradient: LinearGradient(
            stops: [0.0, 1.0], //[渐变起始点, 渐变结束点]
            //渐变颜色[始点颜色, 结束颜色]
            colors: [
              Color(0x55000000),
              Color(0x00000000),
            ],
          ),
        ),
      ),
    );

    return InkWell(
      onTap: onTap,
      child: Container(
        color: color,
        height: height,
        width: double.infinity,
        child: Stack(
          children: [
            Positioned.fill(
              child: Column(
                children: [
                  Expanded(child: content),
                  line,
                ],
              ),
            ),
            Positioned(
              left: itemWidthBuilder(context, 0) + shadowOffset,
              top: 0,
              child: shadow,
            ),
          ],
        ),
      ),
    );
  }
}
